package project.base.common.config

import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware
import org.springframework.stereotype.Service

/**
 * 容器工具
 * 用于没有归入spring框架管理的类，需要调用spring容器中bean的场景
 * @author 三味
 * @since 2022/3/3 15:20
 */
@Service
class SpringContextHolder : ApplicationContextAware {

    private var applicationContext: ApplicationContext? = null

    /**
     * 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.
     */
    override fun setApplicationContext(applicationContext: ApplicationContext) {
        SpringContextHolder().applicationContext = applicationContext
    }

    /**
     * 取得存储在静态变量中的ApplicationContext.
     */
    fun getApplicationContext(): ApplicationContext? {
        checkApplicationContext()
        return applicationContext
    }

    /**
     * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    @SuppressWarnings("unchecked")
    fun <T> getBean(name: String?): T {
        checkApplicationContext()
        return applicationContext!!.getBean(name) as T
    }

    /**
     * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    @SuppressWarnings("unchecked")
    fun <T> getBean(clazz: Class<T>?): MutableMap<String, T> {
        checkApplicationContext()
        return applicationContext!!.getBeansOfType(clazz)
    }

    /**
     * 清除applicationContext静态变量.
     */
    fun cleanApplicationContext() {
        applicationContext = null
    }

    private fun checkApplicationContext() {
        checkNotNull(applicationContext) { "applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder" }
    }

}
